﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace Najak.Editor
{
	public class GameEditorPlayer : PlayerEntity
	{
		static public GameEditorPlayer Instance { get; private set; }

		public Entity.SelectionManager Selections;

		public GameEditorPlayer(bool isUserControlled)
			: base(isUserControlled)
		{
			IsSelectable = false;
			InputHandler.Instance.RegisterForKeyEvent(this, ProcessKeyCommand, false, true, Keys.W, Keys.F, Keys.S, Keys.A, Keys.B, Keys.D, Keys.E, Keys.V, Keys.M, Keys.OemPlus, Keys.OemMinus);
			InputHandler.Instance.RegisterForKeyEvent(this, Keys.Z, ProcessKeyCommand, false, true, true);
			InputHandler.Instance.RegisterForKeyEvent(this, Keys.Y, ProcessKeyCommand, false, true, true);
			InputHandler.Instance.RegisterForKeyEvent(this, Keys.Delete, ProcessKeyCommand, false, false);
			for (Keys k = Keys.D0; k <= Keys.D9; k++)
			{
				InputHandler.Instance.RegisterForKeyEvent(this, k, ProcessKeyCommand, false, true);
			}

			InputHandler.Instance.RegisterForMouseEvent(this, MouseEventTypes.ButtonClick, MouseButtons.Left, KeyboardModes.Normal, _HandleTileSelect);

		}
		protected override void OnAddedToScene()
		{
			base.OnAddedToScene();
			Instance = this;
			Selections = new Entity.SelectionManager(Scene, this);
			Selections.Activate();

			if (BrushEntity != null)
				BrushEntity.Dispose();
		}

		protected override void OnRemovedFromScene(Scene scene)
		{
			if (Instance == this)
				Instance = null;

			Selections.DeActivate();

			base.OnRemovedFromScene(scene);
		}

		private void _HandleTileSelect(MouseEvent evt)
		{
			Tile tCurrent = Scene.GetTileAtCoordinate(evt.MapCoordinate);
			Portal p = tCurrent as Portal;
			if (p != null)
			{
				OpenObjectEditor(p);
			}
		}

		protected override void OnLoadContent()
		{
			_texture = Scene.Content.Load<Texture2D>("Entities/CrossHairs");
			_origin = new Vector2(_texture.Width / 2.0f, _texture.Height / 2.0f);
		}
		public override void Draw(SpriteBatch spriteBatch, Vector2 offset)
		{
			spriteBatch.Draw(_texture, Location + offset, null, Color, 0.0f, _origin, 0.1f, SpriteEffects.None, 0.0f);
			App.Instance.PostDrawCommands += Selections.Draw;

			if (BrushEntity != null || BrushTile != null)
			{
				Editor.Brush brush = Editor.EditorWindow.Instance.Brush;
				MouseState ms = InputHandler.GetMouseState();
				Coordinate c = Scene.GetCoordAtPixelLocation(ms.X, ms.Y);
				Point mouseLoc = new Point((int)ms.X, (int)ms.Y);

				bool isDrawn = false;

				if (BrushEntity != null)
				{
					BrushEntity._scene = Scene;
					BrushEntity.LoadContent();
					BrushEntity._scene = null;
					Color color = BrushEntity.Color;
					color.A = 64;

					if (BrushEntity.Texture != null)
					{
						isDrawn = true;
						foreach (Coordinate c2 in brush.GetCoverage(mouseLoc, Scene))
						{
							Vector2 loc = c2.ToLocation() + offset;
							spriteBatch.Draw(BrushEntity.Texture, loc, null, color, 0.0f, BrushEntity.Origin, 1.0f, SpriteEffects.None, 0.0f);
						}
					}
				}
				else if (BrushTile != null)
				{
					BrushTile.LoadContent(Scene);
					Vector2 halfTile = new Vector2(-Tile.Size.X / 2, -Tile.Size.Y / 2);

					if (BrushTile.Texture != null)
					{
						isDrawn = true;
						Color color = new Microsoft.Xna.Framework.Color(255, 255, 255, 64);
						foreach (Coordinate c2 in brush.GetCoverage(mouseLoc, Scene))
						{
							Vector2 loc = c2.ToLocation() + halfTile + offset;
							spriteBatch.Draw(BrushTile.Texture, loc, color);
						}
					}
				}

				if (!isDrawn)
				{	// Just draw a transparent magenta rectangle
					Coordinate minC = new Coordinate(int.MaxValue, int.MaxValue);
					Coordinate maxC = new Coordinate(int.MinValue, int.MinValue);

					foreach (Coordinate c2 in brush.GetCoverage(mouseLoc, Scene))
					{
						minC.Row = Math.Min(minC.Row, c2.Row);
						minC.Column = Math.Min(minC.Column, c2.Column);
						maxC.Row = Math.Max(maxC.Row, c2.Row);
						maxC.Column = Math.Max(maxC.Column, c2.Column);
					}
					int width = 1 + maxC.Column - minC.Column;
					int height = 1 + maxC.Row - minC.Row;

					Rectangle rect = new Rectangle((minC.Column * Tile.Size.X) - (int)Scene.VportOffset.X, (minC.Row * Tile.Size.Y) - (int)Scene.VportOffset.Y, width * Tile.Size.X, height * Tile.Size.Y);
					Drawing.Shapes.Instance.FillRectangle(rect, new Color(192, 192, 192, 64));
				}
			}
		}

		protected override void DetermineBoost(KeyboardState keyboardState, GameTime gameTime)
		{
			if (!keyboardState.IsKeyDown(Keys.LeftShift))
			{
				_timeWhenBoostExpires = (long)gameTime.TotalGameTime.TotalMilliseconds + 300;
			}
		}

		static public Tile BrushTile = Tile.DefaultTile;
		static public Entity BrushEntity = null;

		public Entity E = null;

		static public Func<Keys, Tile> GetTileModelForKey;
		static public Func<Keys, Entity> GetEntityModelForKey;

		private bool ConsumeKey(Keys key)
		{
			if (key == Keys.S)
			{
				Scene.Instance.SaveIfNeeded();
			}
			else if (key == Keys.Z)
			{
				Scene.Instance.EditorActions.UndoLastAction();
			}
			else if (key == Keys.Y)
			{
				Scene.Instance.EditorActions.RedoLastAction();
			}
			else if (key == Keys.OemPlus)
			{
				SwitchScene(Scene.Manager.Instance.GetNextSceneName(Scene.Instance.Name));
			}
			else if (key == Keys.OemMinus)
			{
				SwitchScene(Scene.Manager.Instance.GetPreviousSceneName(Scene.Instance.Name));
			}
			else if (key == Keys.Delete)
			{
				if (Selections.SelectedEntities.Count() > 0)
				{
					Editor.EditorAction a = new Editor.Actions.DeleteEntityAction(Selections.SelectedEntities);
					a.Apply();
					Selections.ClearSelection();
				}
			}
			else
			{	// none of these
				return false;
			}
			return true; // key was consumed

		}

		private void ProcessKeyCommand(Keys key)
		{
			if (ConsumeKey(key))
				return; // done

			Tile brushTile = GetTileModelForKey(key);
			Entity brushEntity = (brushTile != null) ? null : GetEntityModelForKey(key);
			
			//if (key >= Keys.D0 && key <= Keys.D9)
			//{
			//   int id = key - Keys.D0;
			//   brushTile = new Portal(id, "Tiles/Portal_1", null);
			//}
			//else if (key == Keys.W)
			//{
			//   brushTile = Assets.Tiles.Wall;
			//}
			//else if (key == Keys.F)
			//{
			//   brushTile = Assets.Tiles.Floor;
			//}
			//else if (key == Keys.D)
			//{
			//   brushTile = Assets.Tiles.SecretDoor;
			//}
			//else if (key == Keys.B)
			//{
			//   brushEntity = Assets.Entities.Barrel;
			//}
			//else if (key == Keys.M)
			//{
			//   brushTile = Assets.Tiles.MapExpander;
			//}

			if (brushEntity != null)
			{
				BrushEntity = brushEntity;
				BrushTile = null;
			}
			else if (brushTile != null)
			{
				BrushTile = brushTile;
				BrushEntity = null;
			}

		}
		private void SwitchScene(string Scene)
		{
			var pt = new Portal.PortalTarget(Scene + ",0,W");

			if (App.Instance.Seconds > s_EarliestTimeToChangeScenes)
			{
				s_EarliestTimeToChangeScenes = App.Instance.Seconds + 0.1;
				App.Instance.LoadNextScene(pt, false);
			}
		}
		static private double s_EarliestTimeToChangeScenes;

		protected override void GetInput(GameTime gameTime)
		{
			base.GetInput(gameTime);
			MouseState mouseState = InputHandler.GetMouseState();

			if (mouseState.RightButton == ButtonState.Pressed)
			{
				var brush = Editor.EditorWindow.Instance.Brush;
				Point mouseLoc = new Point(mouseState.X, mouseState.Y);

				if (BrushTile != null)
				{
					Editor.Actions.PlaceTileAction placeTileAction = new Editor.Actions.PlaceTileAction(BrushTile);

					foreach (Coordinate c in brush.GetCoverage(mouseLoc, Scene))
					{
						_PlaceTileAtCoord(c, placeTileAction);
						Scene.UpdateVportPos();
					}
					placeTileAction.Apply();
				}
				else if (BrushEntity != null)
				{
					Editor.Actions.PlaceEntityAction placeAction = new Editor.Actions.PlaceEntityAction(BrushEntity.Clone());

					foreach (Coordinate c in brush.GetCoverage(mouseLoc, Scene))
					{
						_AddEntityAtCoord(c, placeAction);
						Scene.UpdateVportPos();
					}
					placeAction.Apply();
				}
			}
		}

		private void _AddEntityAtCoord(Coordinate loc, Editor.Actions.PlaceEntityAction pa)
		{
			int column = loc.Column;
			int row = loc.Row;
			if (column < 0 || row < 0 || column >= Scene.Width || row >= Scene.Height)
			{
				Scene.ExpandSize(column, row);
				column = Math.Max(column, 0);
				row = Math.Max(row, 0);
			}

			pa.AddLocation(loc.ToLocation());
		}

		private void _PlaceTileAtCoord(Coordinate loc, Editor.Actions.PlaceTileAction pa)
		{
			int column = loc.Column;
			int row = loc.Row;
			if (column < 0 || row < 0 || column >= Scene.Width || row >= Scene.Height)
			{
				Scene.ExpandSize(column, row);
				column = Math.Max(column, 0);
				row = Math.Max(row, 0);
			}

			pa.AddLocation(loc);
			
		}

		private Tile _lastEditedTile;
		static public string LastScenePD;

		public void OpenObjectEditor(Tile t)
		{
			if (ObjectEditor.Instance != null)
			{
				if (_lastEditedTile == t)
				{
					return;
				}
				else
				{
					ObjectEditor.Instance.Close();
				}
			}
			_lastEditedTile = t;
			//Game.IsPaused = true;
			ObjectEditor.EditObject(t);


			//Game.IsPaused = false;


		}

		

		private int _tCount;




	}

}
